package com.newtribe.security;

import java.security.*;
import java.security.interfaces.*;
import javax.crypto.*;
import java.io.*;
import java.security.spec.*;
import javax.crypto.spec.*;
import java.util.*;
import java.security.*;
import java.security.cert.Certificate;
import java.io.* ;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import sun.misc.BASE64Encoder;
import sun.misc.BASE64Decoder;

import org.dom4j.Document;
import org.dom4j.*;
import org.dom4j.io.*;
import java.io.* ;


public class privacy {
  public privacy() {
  }
    public static void main(String[] args) throws Exception{


//      File f =new File("D:/privacy/license.dat") ;
//
//      FileInputStream in =new FileInputStream(f) ;
//      byte[] b =new byte[(int)f.length()] ;
//
//      int count =0 ;
//      while (true ) {
//        int n =in.read() ;
//        if (n ==-1)break ;
//       b [count ++] = (byte) n ;
//
//      }
//
//      String b="itSlNAu0ET/w/KAO5AevQE4lPoi1jIag54/d/zNFYDn4R0QlsHWDRCRbpi4+qfqSnROv7BLy05vGG9XkN9+t2A==" ;
//    verify("211.88.25.104","2008-10-10", b) ;

//validateCDATA();
      // sign("211.88.25.104","2008-10-10","111111") ;

       if (args ==null  ||args.length <3 ) {
         System.out.println("\nargs error ......\n"+
                            "privacy ip expiration password\n"+
                            "args[0] the server ip  \n"+
                            "args[1] expiration like 2008-10-10 \n"+
                            "args[2] keystore password ");
         return ;
       }
       sign(args[0] ,args[1],args[2]) ;
    }
  public static void genKeyPair() throws Exception {
    KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
    keyPairGen.initialize(512);
    KeyPair keyPair = keyPairGen.genKeyPair();

    RSAPublicKey pubKey = (RSAPublicKey) keyPair.getPublic();
    RSAPrivateKey priKey = (RSAPrivateKey) keyPair.getPrivate();

    byte[] pubKeyBytes = pubKey.getEncoded();
    FileOutputStream fos = new FileOutputStream("keys/pubkey");
    fos.write(pubKeyBytes);
    fos.close();

    byte[] priKeyBytes = priKey.getEncoded();
    fos = new FileOutputStream("keys/prikey");
    fos.write(priKeyBytes);
    fos.close();

  }
  public static String toBase64(byte[] buf) {
return (new BASE64Encoder()).encode(buf);
}

  public static byte[] fromBase64(String buf) throws Exception{
    return (new BASE64Decoder()).decodeBuffer(buf);
  }

  public static void sign (String ip ,String date ,String pwd) throws Exception  {

     String signValue =getSignedValue(ip ,date,pwd) ;

     createLicenseFile(ip,date,signValue) ;
     System.out.println("Success...license file created [license.dat]....");

  }
  static void validateCDATA() throws Exception {
    SAXReader reader = new SAXReader();

    //�������dom������,
    InputStream in = new FileInputStream(dir + "license.dat");
    if (in == null)
      throw new Exception("no license template found! .");
    Document doc = reader.read(in);
    in.close();

    Element signature = (Element) doc.selectSingleNode("//gfa-licenses/license");
    String text = signature.getText() ;


  }
  static void createLicenseFile(String ip ,String date ,String signValue ) throws Exception {

    SAXReader reader = new SAXReader();

    //�������dom������,
    InputStream in = new FileInputStream(dir+"license.tdl");
    if (in == null)
      throw new Exception("no license template found! .");
    Document doc = reader.read(in);
    in.close();
    ///////////////create signature value
    Node expiration = doc.selectSingleNode("//gfa-licenses/license/@expiration");
    expiration.setText(date);
    Node ipaddr = doc.selectSingleNode("//gfa-licenses/license/@ip");
    ipaddr.setText(ip);
//    Node signature = doc.selectSingleNode("//gfa-licenses/license/@signature");
//   signature.setText(signValue);

    Element signature = (Element) doc.selectSingleNode("//gfa-licenses/license");
    signature.addCDATA(signValue);



    ///////////////end create signature value
    OutputStream os = new java.io.
        FileOutputStream(dir+"license.dat");
    OutputFormat format = new OutputFormat();
    format.setEncoding("utf-8");



    XMLWriter writer = new XMLWriter(os, format);

//  Document domresult = DocumentHelper.parseText(xml.toString());
//����ݿ��в�ѯ֮��Ľ��(xml��Dom�����ͻ�ȥ)
     writer.write(doc);
     writer.close();
     os.flush();
     os.close()  ;


  }

  static String dir ="" ;
  static String getSignedValue(String ip, String date, String pwd) throws
      Exception {

    KeyStore keystore = KeyStore.getInstance("jks");

    InputStream in = new FileInputStream(dir+"pivacy.jks");
    keystore.load(in, pwd.toCharArray());
    in.close();

    PrivateKey k = (PrivateKey) keystore.getKey("gfa", pwd.toCharArray());

    java.security.Signature signet = java.security.Signature.getInstance(
        "SHA1withRSA");
    signet.initSign(k);
    signet.update((ip+date).getBytes());
    byte[] signed = signet.sign();
    String data =toBase64(signed) ;

//    byte[] test =fromBase64(data) ;
//    f("d:/a.dat",signed) ;
//    f("d:/b.dat",test) ;


    return data ;

  }
  static void f (String name ,byte[] d)throws Exception {
     FileOutputStream out =new FileOutputStream(name) ;
     out.write(d);
     out.close();
  }

    public static void verify (String ip ,String date ,String signed64 ) throws Exception  {
      java.security.Signature signetcheck = java.security.Signature.
          getInstance("SHA1withRSA");
          PublicKey pubkey = getPubKeyBASE64(pubKey) ;
      signetcheck.initVerify(pubkey);
      signetcheck.update(("211.88.25.1042008-10-10").getBytes());

      byte[] signed = fromBase64(signed64) ;
      if (signetcheck.verify(signed)) {
        System.out.println("ǩ����");
      }

    }

    public boolean  verifyLicense(String file ) throws Exception {

      SAXReader reader = new SAXReader();


      InputStream in = new FileInputStream(file);
      if (in == null)
        throw new Exception("no license file specified! .");
      Document doc = reader.read(in);
      in.close();
  ///////////////create signature value
      Node expiration = doc.selectSingleNode("//gfa-licenses/license/@expiration");
      Node ipaddr = doc.selectSingleNode("//gfa-licenses/license/@ip");

      String exp=expiration.getText() ;
      String ip =ipaddr.getText()+" s" ;

      String signedString =   doc.selectSingleNode("//gfa-licenses/license").getText();
      java.security.Signature signetcheck = java.security.Signature.
          getInstance("SHA1withRSA");
      PublicKey pubkey = getPubKeyBASE64(pubKey);
      signetcheck.initVerify(pubkey);
      signetcheck.update( (ip+exp).getBytes());

      byte[] signed = fromBase64(signedString);
      if (signetcheck.verify(signed)) {
        System.out.println("==========license file ok");
        return false ;
      }else {
                System.out.println("***********license file failed");
                return true ;
      }

    }

    public static void verifyByCert(String ip, byte[] signed) throws Exception {
    	
    	      CertificateFactory certFactory = CertificateFactory.getInstance("X.509") ;


          InputStream in =new FileInputStream("D:/privacy/cert.cer") ;

           X509Certificate x =  (X509Certificate)certFactory.generateCertificate(in) ;


      java.security.Signature signetcheck = java.security.Signature.
          getInstance("SHA1withRSA");
      //PublicKey pubkey = getPubKeyByBASE64(pubKey);
       PublicKey pubkey = x.getPublicKey() ;
      signetcheck.initVerify(pubkey);
      signetcheck.update(ip.getBytes());

      if (signetcheck.verify(signed)) {
        System.out.println("passed verify");
      }

    }


    public static PublicKey getPubKeyBASE64(String pubStr)
  {
   try {
      byte[] pubBy = new BASE64Decoder().decodeBuffer(pubStr);
      X509EncodedKeySpec spec = new X509EncodedKeySpec(pubBy);
      KeyFactory keyFactory = null;

      keyFactory = KeyFactory.getInstance("RSA");

      PublicKey pubKey = keyFactory.generatePublic(spec);
      return pubKey;
    }
    catch (Exception ex)
    {
      ex.printStackTrace();
    }
    return null;


  }





  private static String pubKey =
      "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJd+ZjDxUzLY+vamgAEzzuWFgi9tOpT1mjS24n7m38LE"+
"CNCT8zRcvYwZ0kA8TKG0c2z3JfG2L/tmQJ09dDB45GsCAwEAAQ" ;





}
